package com.whales.shared.util;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.StringReader;
import java.io.StringWriter;
import java.net.InetSocketAddress;
import java.net.Socket;

import org.jdom.Document;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
import org.jdom.output.XMLOutputter;
import org.springframework.stereotype.Service;

import com.whales.shared.service.BaseService;

@Service
public class AgentUtil extends BaseService {
	private Socket socket;
	private int socketBufferSize = -1;
	private XMLOutputter op = new XMLOutputter();;
	private InputStream pis;
	private OutputStream pos;
	private SAXBuilder builder = new SAXBuilder();
	
	public String sendXml(String ip, Document command, String resultElement){
		try {
			//opensocket
			this.openSocket(ip, Integer.parseInt(super.getProperty("AGENT_PORT"))); //port : 9091
			//sendMessage
			this.sendMessage(command);
			//receiveMessage
			Document receiveDoc = this.recieveMessage();
			//closesocket
			this.closeSocket();
			return receiveDoc.getRootElement().getChildText(resultElement);
		} catch (Exception e) {
			e.printStackTrace();
			return "ERR";
		}
	}
	
	public String sendXml(String ip, Document command){
		return this.sendXml(ip, command, "result");
	}
	
	private void sendMessage(Document protocol) throws IOException {
		StringWriter sw = new StringWriter();
		op.output(protocol, sw);
		String xmlString = sw.toString().trim();
		pos.write(xmlString.getBytes("UTF-8"));
		pos.flush(); 
	}
	
	private Document recieveMessage() throws IOException, JDOMException {
		Document protocol = null;
		int b = -1;
		int[] endTag = {'<','/','a','g','e','n','t','-','r','e','s','p','o','n','s','e','>'};
		int checkIndex = 0;
		
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		while((b = pis.read()) != -1) {
			baos.write(b);					
			if(endTag[checkIndex] == b) {
				checkIndex++;
			} else {
				checkIndex = 0;
			}
			if(checkIndex == endTag.length) break;
		}
        StringReader sr = new StringReader(new String(baos.toByteArray(), "utf-8").trim());
        protocol = builder.build(sr);
        sr.close();
		return protocol;
	}
	
	private void openSocket(String ip, int port) throws Exception{
		socket = new Socket();
		socket.setSoTimeout(1000); //timeout 1초로 설정
		if(socketBufferSize > -1) {
			socket.setReceiveBufferSize(socketBufferSize);
			socket.setSendBufferSize(socketBufferSize);
		}
		socket.connect(new InetSocketAddress(ip, port));
		pis = new BufferedInputStream(socket.getInputStream());
		pos = new BufferedOutputStream(socket.getOutputStream());
		
	}
	
	private void closeSocket() {
		try {
			if(pis != null) pis.close();
			if(pos != null) pos.close();
			if(socket != null) socket.close();
		} catch (IOException ignored) {} // NOPMD
	}
}
